//;******************************************************************************
//;* Copyright (c) 1983-2010, Insyde Software Corporation. All Rights Reserved.
//;*
//;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
//;* transmit, broadcast, present, recite, release, license or otherwise exploit
//;* any part of this publication in any form, by any means, without the prior
//;* written permission of Insyde Software Corporation.
//;*
//;******************************************************************************
/*++
  This file contains an 'Intel Pre-EFI Module' and is licensed
  for Intel CPUs and Chipsets under the terms of your license
  agreement with Intel or your vendor.  This file may be
  modified by the user, subject to additional terms of the
  license agreement
--*/
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.

Module Name:

  pciUtilAdv.c

Abstract:

  pci utilies in EFI shell

--*/

#include "efi.h"
#include "shell.h"
#include "pci22.h"
#include "ReadOutPci.h"
#include "DumpPCI.h"
#include "DumpPciConfigureSpace.h"
#include "WriteValueToPciConfigSpace.h"



typedef enum {
  DEVICE_LIST_MODE     = 0x100,
  CONFIGURE_SPACE_MODE = 0x200  
} SHELL_MODE;

  









EFI_APPLICATION_ENTRY_POINT (pciUtilAdv)

/*++

Routine Description:
  Initialize the PEI emulation shell command

Arguments:
  (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)

Returns:

--*/

EFI_STATUS
pciUtilAdv(
  IN EFI_HANDLE                            ImageHandle,
  IN EFI_SYSTEM_TABLE                      *SystemTable
  )
/*++

Routine Description:
  Collect PCI Data

Arguments:

Returns:
  
--*/
{

  
  BOOLEAN       isWaiting;
  UINT8         *Value8;
  UINT16        BarRow;
  UINT16        BarOffset;
  UINT16        BarStartPosition;
  UINT16        BarEndPosition;
  UINT16        PciDeviceNumber;
  UINT16        ConfCol;
  UINT16        ConfColStart;
  UINT16        ConfColEnd;
  UINT16        ConfColOffset; 
  UINT16        ConfRow;
  UINT16        ConfRowEnd;
  UINT16        ConfRowStart;
  UINT16        ConfRowOffset;
  CHAR16        StrInput[3];
  SHELL_MODE    Mode;      
//  EFI_STATUS    Status;
  EFI_INPUT_KEY KeyBuffer;
  PCITable      PciTable[30];
 // UINTN  V;
  
  
  InitializeShellApplication(ImageHandle, SystemTable);

  isWaiting = 1;
  PciDeviceNumber = 0;
  BarStartPosition = 0;
  BarRow =    0;
  BarOffset = 2;
  ConfColOffset = 3;
  ConfCol = 0;
  ConfColStart = 0;
  ConfColEnd = ConfColStart + 15;
  ConfRow = 0;
  ConfRowOffset = 1;
  ConfRowEnd = 15;
  ConfRowStart = 0;

  Mode = DEVICE_LIST_MODE;
 

  ReadoutPCI(&PciDeviceNumber,
             PciTable
             );  

  BarEndPosition = BarRow + PciDeviceNumber;

//  Print(L"%d\n\r", PciDeviceNumber);

  DumpPCI(PciDeviceNumber,
          PciTable);
  
 while(isWaiting){
	 // Block Wait for Key
	 WaitForSingleEvent (ST->ConIn->WaitForKey, 100);
	 ST->ConIn->ReadKeyStroke (ST->ConIn, &KeyBuffer);

	 
	 switch ( KeyBuffer.ScanCode + Mode ) {

	   //
	   // Press ESC
	   //
	   case 0x117:

	     ST->ConOut->OutputString(ST->ConOut,L"hello, world\n\r");
		   ST->ConOut->SetAttribute(ST->ConOut, 
									       EFI_BACKGROUND_BLACK
									       );
		   ST->ConOut->ClearScreen(ST->ConOut);
		   isWaiting = 0;

       
	     break;

       //
         // Press ESC
         //
         case 0x217:
       
           ST->ConOut->OutputString(ST->ConOut,L"hello, world\n\r");
           ST->ConOut->SetAttribute(ST->ConOut, 
                             EFI_BACKGROUND_BLACK
                             );
           ST->ConOut->ClearScreen(ST->ConOut);
           isWaiting = 0;
       
           
           break;

       

       //
       // Press Move Up 1 Row - DEVICE_LIST_MODE
	     //
       case 0x101:
        
         
         if (BarRow == BarStartPosition){
               BarRow = BarStartPosition;             
         }

         else
           BarRow--;
          
         ST->ConOut->ClearScreen(ST->ConOut);      
         ST->ConOut->SetCursorPosition(ST->ConOut, 0, 0);
         
         DumpPCI(PciDeviceNumber,
                 PciTable);
         
         ST->ConOut->SetCursorPosition(ST->ConOut, 0, BarRow + BarOffset);
  
         ST->ConOut->SetAttribute(ST->ConOut, 
  									       EFI_BACKGROUND_GREEN
  									       );
  	   	// ST->ConOut->OutputString(ST->ConOut,L"hello, Rachel\n\r");

         Print(L" %-02x   ",
               PciTable[ BarRow - BarStartPosition].Bus
               );

         Print(L"%-02x      ",
               PciTable[ BarRow - BarStartPosition].Device
               );

         Print(L"%-02x      ",
                  PciTable[ BarRow - BarStartPosition].Func
               );

         Print(L"%-04x     ",
               PciTable[ BarRow - BarStartPosition].PCIData.Hdr.VendorId
               );

         Print(L"%-04x    ",
                PciTable[ BarRow - BarStartPosition].PCIData.Hdr.DeviceId
                );

         
         Print(L"%-04x    ",
                PciTable[ BarRow - BarStartPosition].PCIData.Device.SubsystemVendorID
                );

         Print(L"%-04x",
                PciTable[ BarRow - BarStartPosition].PCIData.Device.SubsystemID
                );

        
         ST->ConOut->SetAttribute(ST->ConOut, 
  			       EFI_BACKGROUND_BLACK
  			       );
  
         ST->ConOut->SetAttribute(ST->ConOut, 
  		                            EFI_LIGHTGRAY
  		                            );
  
         
  
         break;
         
       //
       // Press Move Down 1 Row - DEVICE_LIST_MODE
       // 
       case 0x102:

         BarRow++;
         if (BarRow >= BarEndPosition){
               BarRow = BarEndPosition - 1;
         } 
         
         ST->ConOut->ClearScreen(ST->ConOut);      
         ST->ConOut->SetCursorPosition(ST->ConOut, 0, 0);
         
         DumpPCI(PciDeviceNumber,
                  PciTable);

         
         ST->ConOut->SetCursorPosition(ST->ConOut, 0, BarRow + BarOffset);
         
         ST->ConOut->SetAttribute(ST->ConOut, 
                           EFI_BACKGROUND_GREEN
                           );
//         ST->ConOut->OutputString(ST->ConOut,L"hello, Rachel\n\r");


         Print(L" %-02x   ",
               PciTable[ BarRow - BarStartPosition].Bus
               );

         Print(L"%-02x      ",
               PciTable[ BarRow - BarStartPosition].Device
               );

         Print(L"%-02x      ",
                  PciTable[ BarRow - BarStartPosition].Func
               );

         Print(L"%-04x     ",
               PciTable[ BarRow - BarStartPosition].PCIData.Hdr.VendorId
               );

         Print(L"%-04x    ",
                PciTable[ BarRow - BarStartPosition].PCIData.Hdr.DeviceId
                );

         
         Print(L"%-04x    ",
                PciTable[ BarRow - BarStartPosition].PCIData.Device.SubsystemVendorID
                );

         Print(L"%-04x",
                PciTable[ BarRow - BarStartPosition].PCIData.Device.SubsystemID
                );

         ST->ConOut->SetAttribute(ST->ConOut, 
               EFI_BACKGROUND_BLACK
               );
         
         ST->ConOut->SetAttribute(ST->ConOut, 
                                  EFI_LIGHTGRAY
                                  );

  
         break;



        //
       // Press Move Up 1 Row - CONF_MODE
	     //
       case 0x201:

        
         
         if (ConfRow == ConfRowStart){
               ConfRow = ConfRowStart;
         } 

         else
          ConfRow--;
    
         DumpPciConfigureSpace( BarRow,
                               PciTable);

          
         ST->ConOut->SetAttribute(ST->ConOut, 
  			                          EFI_RED
  			                          );



         ST->ConOut->SetCursorPosition(
                                       ST->ConOut,
                                       ConfCol * 3 + ConfColOffset,
                                       ConfRow + ConfRowOffset
                                       );


         Value8 = (UINT8*) (PciTable + BarRow);
         
         Print(L"%-02x", *(Value8 + ( ConfRow * 16) + ConfCol) );
         //Print(L" Row = %d", ConfRow);

  
         ST->ConOut->SetAttribute(ST->ConOut, 
  		                            EFI_BACKGROUND_BLUE
  		                            );
  

         break;


        //
       // Press Move Down 1 Row - CONF_MODE
       // 
       case 0x202:

         ConfRow++;
         if (ConfRow >= ConfRowEnd){
               ConfRow = ConfRowEnd;
         } 
         
         ST->ConOut->ClearScreen(ST->ConOut);      
         ST->ConOut->SetCursorPosition(ST->ConOut, 0, 0);
         
         DumpPciConfigureSpace(BarRow,
                  PciTable);

        ST->ConOut->SetAttribute(ST->ConOut, 
                                   EFI_RED
                                   );      
        
         ST->ConOut->SetCursorPosition(ST->ConOut, 
                                       ConfCol * 3 + ConfColOffset, 
                                       ConfRow + ConfRowOffset                                      
                                       );

         Value8 = (UINT8*) (PciTable + BarRow);
         
         Print(L"%-02x", *(Value8 + (ConfRow  * 16 + ConfCol)) );  
         //Print(L" Row = %d", ConfRow);

         ST->ConOut->SetAttribute(ST->ConOut, 
               EFI_BACKGROUND_BLUE
               );
         
     
         break; 



         //
         // Press Move Right - CONF MODE 
         //
         case 0x203:
           
            ConfCol++;
            if (ConfCol >= ConfColEnd){
                  ConfCol= ConfColEnd;
            } 
            
            ST->ConOut->ClearScreen(ST->ConOut);      
            ST->ConOut->SetCursorPosition(ST->ConOut, 0, 0);
            
            DumpPciConfigureSpace(BarRow,
                     PciTable);
   
           ST->ConOut->SetAttribute(ST->ConOut, 
                                      EFI_RED
                                      );      
           
            ST->ConOut->SetCursorPosition(ST->ConOut, 
                                          ConfCol *3 + ConfColOffset, 
                                          ConfRow + ConfRowOffset                                      
                                          );
   
            Value8 = (UINT8*) (PciTable + BarRow);
            
            Print(L"%-02x", *(Value8 + (ConfRow  * 16 + ConfCol)) );  
//            Print(L" Col = %d", ConfCol);
   
            ST->ConOut->SetAttribute(ST->ConOut, 
                  EFI_BACKGROUND_BLUE
                  );
            
     
          
          

           break;


         //
         // Press Move Left - CONF_MODE
         //
         case 0x204: 

            
            if (ConfCol == ConfColStart){
                  ConfCol= ConfColStart;
            } 

            else
              ConfCol--;
            
            ST->ConOut->ClearScreen(ST->ConOut);      
            ST->ConOut->SetCursorPosition(ST->ConOut, 0, 0);
            
            DumpPciConfigureSpace(BarRow,
                     PciTable);
   
           ST->ConOut->SetAttribute(ST->ConOut, 
                                      EFI_RED
                                      );      
           
            ST->ConOut->SetCursorPosition(ST->ConOut, 
                                          ConfCol * 3 + ConfColOffset, 
                                          ConfRow + ConfRowOffset                                      
                                          );
   
            Value8 = (UINT8*) (PciTable + BarRow);
            
            Print(L"%-02x", *(Value8 + (ConfRow  * 16 + ConfCol)) );  
//            Print(L" Col = %d", ConfCol);
   
            ST->ConOut->SetAttribute(ST->ConOut, 
                  EFI_BACKGROUND_BLUE
                  );
            
       
     

          
           break;
       
              //
              // Press F1  - Dump PCI
              // 
              case 0x20B:
       
               DumpPCI(1,
                       PciTable);

               Mode = DEVICE_LIST_MODE;
       
                break;


         


       //
       // Press F2 - Dump Conf Space
       // 
       case 0x10C:


//           DrawDumpPciConfigureSpaceBorder();
           DumpPciConfigureSpace(BarRow, 
                                 PciTable);

           Mode = CONFIGURE_SPACE_MODE;

         break; 

       //
       // Press "F3" - CONF_MODE
       //
       case 0x20D:
    
    
            DumpPciConfigureSpaceWord(BarRow,
                                      PciTable
                                      );
   
               Mode = CONFIGURE_SPACE_MODE;
    
             break; 

         

	  default:	     
	    break;
	 }


   //
   //  Press "Enter" - DEVICE_LIST_MODE
   //
	 if ( (KeyBuffer.UnicodeChar == 0x000D) && ( Mode == DEVICE_LIST_MODE) ){

       Mode = CONFIGURE_SPACE_MODE;
       DumpPciConfigureSpace( BarRow,
                              PciTable);

   

	 	}


   //
   // Press "Enter" - CONF_MODEs
   //
   else
   if( (KeyBuffer.UnicodeChar == 0x000D) && (Mode == CONFIGURE_SPACE_MODE) )
   {
//       Mode = DEVICE_LIST_MODE;


       ST->ConOut->SetAttribute(ST->ConOut, 
                           EFI_RED
                           );      
       
       ST->ConOut->SetCursorPosition(ST->ConOut, 
                                          0, 
                                          22                                     
                                          );


        
       Input( L"Modify Value to :",
              StrInput, 
              sizeof(StrInput)/sizeof(CHAR16)
              );

  //    V = xtoi(StrInput);
       WriteValueToPciConfigSpace8(StrInput,
                                   PciTable,
                                   BarRow,
                                   ConfRow *16 + ConfCol
                                   );
  
      
      

       DumpPciConfigureSpace( BarRow, 
                              PciTable);

 /*      
             ST->ConOut->SetCursorPosition(ST->ConOut, 
                                          0, 
                                          22                                     
                                          );
       Print(L"%-02x", V);

   */    

	 }





  
}

 return EFI_SUCCESS;
}









